import random;
from xml.dom.minidom import parse;
from Activity import Activity;

class InputSim(object):
    def __init__(self, stgm, nSeed, nTimes, bReadXML=True, sXmlFile=""):
        self.stgm = stgm;
        self.nSeed = nSeed;
        random.seed(nSeed);
        self.nTimes = nTimes;
        self.bReadXML = bReadXML;
#        self.sXmlFile = sXmlFile;
        self.initInput(bReadXML, sXmlFile);
        
    def initInput(self, bReadXML, sXmlFile=""):
        #Fill All [STATIC] Activity names & Person Ids to Track
        self.setupRndSubjects();
        self.nPersons = [1,2,2,2];
        self.sActivities = ["Loitering", "Wait-N-Meet", "Chase", "Approach"];
        self.aActs_Time = dict();
#        if bReadXML:
#            self.makeXmlActivities(sXmlFile);
#        else:
#            self.makeRndActivities();
        self.makeStateSpace();
        self.nStates = self.getNumStates();
        self.buildTransitionM();
        self.buildMarkovM();
        self.buildPriors();
        
    def setupRndSubjects(self):
        self.sPersons = ["*"]
        for i in range(3):
            self.sPersons.append("P"+str(i+1));
        
    def makeStateSpace(self):
        sPersonsC2 = [["A", "*"], ["A", "B"], ["B", "*"], ["B", "A"], ["*", "A"], ["*", "B"]];
        sPersonsC1 = ["A"];
        self.aStates = [];
        for i in range(len(self.sActivities)):
            if self.nPersons[i] == 1:
                self.aStates.append([self.sActivities[i], sPersonsC1]);
            elif self.nPersons[i] == 2:
                for j in range(len(sPersonsC2)):
                    self.aStates.append([self.sActivities[i], sPersonsC2[j]]);
    
    def makeXmlActivities(self, sXmlFile=""):
        xmlAct = parse(sXmlFile);
        actCollection = xmlAct.documentElement;
        actElements = actCollection.getElementsByTagName("activity");
        self.aActivities = []; #All Activities read from XML
        for actItem in actElements:
            #Activity:
            self.createAct(actItem, bRoot=True);
            #Check SubActivities:
            subActElements = actItem.getElementsByTagName("sub-activity");
            for subActItem in subActElements:
                #SubActivity:
                self.createAct(subActItem, bRoot=False, activity=self.aActivities[-1]);
        print "---Activity Nodes from XML:";
        for actNode in self.aActivities:
            self.printActNode(actNode);
        self.nTimes = len(self.aActivities);
                
    def createAct(self, actItem, bRoot=False, activity=None):
        aSubjects = [];
        aSubjectTypes = [];
        aObjects = [];
        aObjectTimes = [];
        aObjectTypes = [];
        subjectElements = actItem.getElementsByTagName("subject");
        objectElements = actItem.getElementsByTagName("object");
        for subjectItem in subjectElements:
            aSubjects.append(subjectItem.firstChild.data);
            aSubjectTypes.append(subjectItem.getAttribute("type"));
        for objectItem in objectElements:
            aObjects.append(objectItem.firstChild.data); #Each corresponds to their respective time in aObjectTimes
            aObjectTypes.append(objectItem.getAttribute("type"));
            if objectItem.getAttribute("time")!="":
                aObjectTimes.append(str(objectItem.getAttribute("time").replace("[","").replace("]","")).split(","));
        sActName = actItem.getAttribute("name");
        if actItem.getAttribute("subject")!="":
            aSubjects.extend(str(actItem.getAttribute("subject").replace("[","").replace("]","")).split(","));
        if actItem.getAttribute("object")!="":
            aObjects.extend(str(actItem.getAttribute("object").replace("[","").replace("]","")).split(","));
#        for aObj in aObjects:
        if len(aObjects)>=1 and aObjects[-1]!="": aSubjects.append(aObjects[-1]);
        if len(aObjects)==1 and aObjects[0]=="": aObjects = [];
        aTimes = str(actItem.getAttribute("time").replace("[","").replace("]","")).split(",");
        nTime = int(aTimes[-1].replace("t","").replace("+",""));
        sId = actItem.getAttribute("id") + "." + str(nTime);
        sParentsId = str(actItem.getAttribute("parents").replace("[","").replace("]","")).split(",");
        if bRoot==False:
            for i in range(len(sParentsId)):
                sParentsId[i] += "." + str(nTime);
        if len(sParentsId)==1 and sParentsId[0]=="": sParentsId = [];
        sScores = str(actItem.getAttribute("score").replace("[","").replace("]","")).split(",");
        aScores = [];
        for strScore in sScores: aScores.append(float(strScore));
        sLocation = actItem.getAttribute("location");
        #Add the Activity or Sub-Activity
        if bRoot: 
            activity = Activity(self.stgm, sActName, aSubjects, nTime, sId);
            self.aActivities.append(activity);
        activity.makeXmlNode(sId, sActName, aSubjects, aObjects, aObjectTypes, aObjectTimes, aTimes, 
                             sParentsId, aScores, sLocation, bRoot);
                             
    def printActNode(self, actNode):
        print "Activity Node:";
        print "sName:", actNode.rootAct.name;
        print "sId:", actNode.rootAct.sId;
        print "sActName:", actNode.rootAct.actName;
        print "aSubjects:", actNode.rootAct.aSubjects;
        print "aObjects:", actNode.rootAct.aObjects;
        print "aObjectTypes:", actNode.rootAct.aObjectTypes;
        print "aObjectTimes:", actNode.rootAct.aObjectTimes;
        print "nTime:", actNode.rootAct.timeId; #Identify node's module in its timepoint.
        print "aTimes:", actNode.rootAct.aTimes;
        print "aScores:", actNode.rootAct.aScores;
        print "sLocation:", actNode.rootAct.location;
        print "sParentsId:", actNode.rootAct.sParentsId;
        print "";
        for subAct in actNode.aChildNodes:
            print "- Sub-Activity Node:";
            print "- sName:", subAct.name;
            print "- sId:", subAct.sId;
            print "- sActName:", subAct.actName;
            print "- aSubjects:", subAct.aSubjects;
            print "- aObjects:", subAct.aObjects;
            print "- aObjectTypes:", subAct.aObjectTypes;
            print "- aObjectTimes:", subAct.aObjectTimes;
            print "- nTime:", subAct.timeId; #Identify node's module in its timepoint.
            print "- aTimes:", subAct.aTimes;
            print "- aScores:", subAct.aScores;
            print "- sLocation:", subAct.location;
            print "- sParentsId:", subAct.sParentsId;
            print "";

    def makeRndActivities(self):
        nId = 0;
        for t in range(self.nTimes):
            aActivities = [];
            nActs = random.randint(1,5);
            for i in range(nActs): #@UnusedVariable
                nAct = random.randint(0,len(self.sActivities)-1);
                sAct = self.sActivities[nAct];
                aPersons = self.getRndArgs(self.nPersons[nAct]);
                nId += 1;
                activity = Activity(self.stgm, sAct, aPersons, t, str(nId));
                aActivities.append(activity);
            self.aActs_Time.append(aActivities);            
            
    def getRndArgs(self, nPersons):
        #Fill Random Arguments about Persons Involved
        aPersons = [];
        rndP1 = random.randint(0,len(self.sPersons)-1);
        rndP2 = random.randint(0,nPersons-1);
        if nPersons==1:
            rndP1 = random.randint(1,len(self.sPersons)-1);
            aPersons = [self.sPersons[rndP1]];
        if nPersons==2:
            while rndP1==rndP2:
                rndP1 = random.randint(0,len(self.sPersons)-1);
                rndP2 = random.randint(0,nPersons-1);
            aPersons.append(self.sPersons[rndP1]);
            aPersons.append(self.sPersons[rndP2]);
        return aPersons;
            
    def getNumStates(self):
        nStates = 0;
        for i in range(len(self.nPersons)):
            if self.nPersons[i]==1:
                nStates += 1;
            elif self.nPersons[i]==2:
                nStates += 6;
        return nStates;
            
    def buildTransitionM(self):
        #Build Transition Matrix
        self.aTrans = [[random.random() for j in range(self.nStates)] for i in range(self.nStates)];
        for i in range(len(self.aTrans)):
            nSum = 0;
            for j in range(len(self.aTrans[i])):
                nSum += self.aTrans[i][j];
            for j in range(len(self.aTrans[i])):
                self.aTrans[i][j] /= nSum;
            
    def buildMarkovM(self):
        #Build Markov Correlation Matrix
        self.aMarkovM = [[0.5 for j in range(self.nStates)] for i in range(self.nStates)]; #@UnusedVariable        
            
    def buildPriors(self):
        #Build Prior Probabilities
        self.aPriors = [random.random() for i in range(self.nStates)]; #@UnusedVariable            
            
    def printStateSpace(self):
        for i in range(len(self.aStates)):
            print i+1, "-", self.aStates[i];   
                
    def printActivities(self):
        #Print All Activities
        for t in range(self.nTimes):
            print "TIME "+str(t+1)+":"; 
            for i in range(len(self.aActs_Time[t])):
                print "-----Activity "+str(i+1)+":"; 
                print "Activity:", self.aActs_Time[t][i].sActivity, "(", self.aActs_Time[t][i].aPersons, ")";
                print "Time:", self.aActs_Time[t][i].nTime;
                print "Likelihood:", self.aActs_Time[t][i].nLikelihood;
            print "";
    
    def printTransitionM(self):
        for i in range(len(self.aTrans)):
            print self.aTrans[i];
            
    def printPriors(self):
        print "";
        print self.aPriors;
        